package norbert.flickr {

	import com.adobe.crypto.MD5;
	
	import flash.net.SharedObject;
	
	import mx.core.IMXMLObject;
	import mx.logging.ILogger;
	import mx.logging.ILoggingTarget;
	import mx.logging.Log;
	import mx.logging.LogEventLevel;
	
	import norbert.flickr.api.Auth;
	
	/**
	 * The FlickrService class abstracts the Flickr API found
	 * at http://www.flickr.com/services/api/
	 */
	public class Flickr implements IMXMLObject {
		private static var logger: ILogger = Log.getLogger("norbert.flickr.Flickr");

		/**
		 * The REST endpoint where we can talk with Flickr service
		 */
		public static const END_POINT:String = "http://api.flickr.com/services/rest/?";
		
		/**
		 * The endpoint where we go for authentication
		 */
		public static const AUTH_END_POINT:String = "http://api.flickr.com/services/auth/?";
		
		[Bindable]
		public static var instance: Flickr;
		
		private var id: String;
		private var document: Object;

		/** 
		 * Store the API key that gives developers access to the Flickr service 
		 */
		private var _api_key:String;
		
		/**
		 * The "shared secret" of your application for authentication
		 */
		private var _secret:String;
		
		/**
		 * The token identifying the user as logged in
		 */
		private var _token:String = "";
		
		/**
		 * One of the consants from the AuthPerm class corresponding
		 * to the current permission the authenticated user has
		 */
		private var _permission:String = Auth.PERMISSION_NONE;

		private var _user:String;
		
		/**
		 * Returns the current API key in use for accessing the Flickr service.
		 *  
		 * @langversion ActionScript 3.0
		 * @playerversion Flash 8.5
		 * @tiptext
		 */
		public function get api_key():String {
			return _api_key;	
		}
		
		/**
		 * Sets the API key that should be used to access the Flickr service.
		 *
		 * @param value The API key to use against Flickr.com
		 * @see http://www.flickr.com/services/api/misc.api_keys.html
		 * @see http://www.flickr.com/services/api/registered_keys.gne
		 * @langversion ActionScript 3.0
		 * @playerversion Flash 8.5
		 * @tiptext
		 */
		public function set api_key( value:String ):void {
			_api_key = value;	
		}
		
		/**
		 * Returns the "shared secret" of the Application associated with
		 * the API key for use in Authentication.
		 * 
		 * @see http://www.flickr.com/services/api/registered_keys.gne
		 * @langversion ActionScript 3.0
		 * @playerversion Flash 8.5
		 * @tiptext
		 */
		public function get secret():String {
			return _secret;	
		}
		
		/**
		 * Sets the "shared secret" to that of an Application configured against
		 * the API key for use in Authentication.
		 *
		 * @param value The "shared secret" of the Application to authenticate 
		 *			against.
		 * @see http://www.flickr.com/services/api/registered_keys.gne
		 * @langversion ActionScript 3.0
		 * @playerversion Flash 8.5
		 * @tiptext
		 */
		public function set secret( value:String ):void {
			_secret = value;	
		}
		
		/**
		 * Returns the token identifying the user as logged in
		 *
		 * @langversion ActionScript 3.0
		 * @playerversion Flash 8.5
		 * @tiptext
		 */
		public function get token():String {
			return _token;	
		}
		
		/**
		 * Sets the token identifyin the user as logged in so that
		 * the FlickrService API can sign the method calls correctly.
		 *
		 * @param value The authentication token
		 * @langversion ActionScript 3.0
		 * @playerversion Flash 8.5
		 * @tiptext
		 */
		public function set token( value:String ):void {
			_token = value;	
			getFlickerSharedObject().data.token = token;
			logger.debug("set token {0}", token);
		}
		
		/**
		 * Returns the permission the application has for the
		 * currently logged in user's account.
		 *
		 * @langversion ActionScript 3.0
		 * @playerversion Flash 8.5
		 * @tiptext
		 */
		public function get permission():String {
			return _permission;
		}
		
		/**
		 * Sets the desired permission for the user's account requested
		 * by the application.  During the login process, the user has
		 * the ability to allow or deny the application the permission.
		 *
		 * @param value One of the consants from the AuthPerm class
		 *			corresponding to the current permission the 
		 *			authenticated user has
		 * @see com.adobe.service.flickr.AuthPerm
		 * @langversion ActionScript 3.0
		 * @playerversion Flash 8.5
		 * @tiptext
		 */
		public function set permission( value:String ):void {
			_permission = value;	
			getFlickerSharedObject().data.permission = permission;
			logger.debug("set permission {0}", permission);
		}
		
		[Bindable]
		public function get user():String {
			return _user;
		}
		public function set user( value:String ):void {
			_user = value;	
			getFlickerSharedObject().data.user = user;
		}

		/* CONSTRUCTOR */
		
		public function Flickr() {
			instance = this;

			var flickrSO: SharedObject = getFlickerSharedObject();
			if (flickrSO.data.hasOwnProperty("token")) {
				token = flickrSO.data.token;
			}
			if (flickrSO.data.hasOwnProperty("permission")) {
				permission = flickrSO.data.permission;
			}
			if (flickrSO.data.hasOwnProperty("user")) {
				user = flickrSO.data.user;
			}
			logger.info("token: {0}; permission: {1}", token, permission); 
		}

		/* METHODS */
		
		public function initialized(document: Object, id: String): void {
			this.id = id;
			this.document = document;
		}
		
		/**
		 * Returns the URL to use for authentication so the developer
		 * doesn't have to build it by hand.
		 *
		 * @param frob The frob from flickr.auth.getFrob to authenticate with
		 * @param permission The permission the user will have after successful
		 *			login
		 * @return The url to open a browser to to authenticate against
		 * @langversion ActionScript 3.0
		 * @playerversion Flash 8.5
		 * @tiptext
		 */
		public function getLoginURL( permission:String, frob:String = null ):String {
			
			var sig:String = secret;
			sig += "api_key" + api_key;
			/* CsNo: If no frob provided, it shouldn't be included in the request. Using this 
			feature it is possible to implement a Web-based authentication */
			if (frob) {
				sig += "frob" + frob;
			}
			sig += "perms" + permission;
			
			var auth_url:String = AUTH_END_POINT;
			auth_url += "api_key=" + api_key;
			/* CsNo: If no frob provided, it shouldn't be included in the request. Using this 
			feature it is possible to implement a Web-based authentication */
			if (frob) {
				auth_url += "&frob=" + frob;
			}
			auth_url += "&perms=" + permission;
			auth_url += "&api_sig=" + MD5.hash( sig );
						
			return auth_url;
		}
		
		private function getFlickerSharedObject(): SharedObject {
			return SharedObject.getLocal("norbert.managr.FLICKR");
		}
	}
}
